#include "music.h"

int flag = 1; //标志
int x;

//音符数组
// int tune[] =
//     {
//         H1, M7, H1, M3, M2, M3, M3, M5,
//         M2, M1, M2, M2, M7, M7, H1, H1, H1, M3, M5, M5,
//         H1, M7, H1, M6, M5, M6, M6, H1,
//         M5, H1, M5, M5, M3, M4, M6, M5, M5, M6, M3, M3, M2,
//         H1, M7, H1, M3, M2, M3, M3, M5,
//         M2, M1, M2, M2, M7, M7, H1, H1, H1, H2, H3, H3,
//         H2, H3, H1, H1, M6, M6, M6, M6,
//         M5, H1, M5, M5, M3, M4, M5, M6, M6, H1, H3, H2,
//         H1, H1, H1};

// //节拍数组
// float duration[] =
//     {
//         1, 1, 1, 1, 0.5, 0.5, 0.5, 1.5,
//         1, 0.5, 0.5, 0.5, 1.5, 1, 0.5, 0.5, 1, 0.5, 0.5, 2,
//         1, 1, 1, 1, 0.5, 0.5, 0.5, 1.5,
//         1, 0.5, 0.5, 0.5, 1.5, 1, 0.5, 0.5, 1, 0.5, 0.5, 0.5, 1.5,
//         1, 1, 1, 1, 0.5, 0.5, 0.5, 1.5,
//         1, 0.5, 0.5, 0.5, 1.5, 1, 0.5, 0.5, 0.5, 1, 0.5, 1,
//         1, 0.5, 0.5, 1, 0.5, 0.5, 1.5, 0.5,
//         1, 0.5, 0.5, 1.5, 0.5, 1, 0.5, 0.5, 0.5, 1.5, 2, 1,
//         2, 2, 2};

// 4/4拍茉莉花
int tune[] = {M3, M3, M5, M6, H1, H1, M6, M5, M5, M6, M5,
              M3, M3, M5, M6, H1, H1, M6, M5, M5, M6, M5,
              M5, M5, M5, M3, M5, M6, M6, M5,
              M3, M2, M3, M5, M3, M2, M1, M1, M2, M1,
              M3, M2, M1, M3, half_M2, M3, M5, M6, H1, M5,
              M2, M3, M5, M2, M3, M1, L6, L5,
              L6, M1, half_M2, M3, M1, M2, M1, L6, L5};
float duration[] = {1, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 1, 0.5, 0.5, 1,
                    1, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 1, 0.5, 0.5, 1,
                    1, 1, 1, 0.5, 0.5, 1, 1, 1,
                    1, 0.5, 0.5, 1, 0.5, 0.5, 1, 0.5, 0.5, 1,
                    0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 1, 0.5, 0.5, 1,
                    1, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 1,
                    1, 1, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 1};

int length = sizeof(tune) / sizeof(tune[0]);
void music_init(int f)
{

    // 这一段代码必考,去改错
    /*时钟使能*/
    RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOF, ENABLE);
    RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM13, ENABLE); // 使能 apb1 tim13
    //1 GPIO-PF8复用--AF--TIM13
    GPIO_InitTypeDef p;
    p.GPIO_Pin = GPIO_Pin_8;
    p.GPIO_Mode = GPIO_Mode_AF; //多路复用模式，注意这个新模式
    p.GPIO_PuPd = GPIO_PuPd_NOPULL;
    p.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_Init(GPIOF, &p);
    // 复用为TIM13
    GPIO_PinAFConfig(GPIOF, GPIO_PinSource8, GPIO_AF_TIM13);
    //2 配置时基单元     5月11 新知识
    /*配置GPIO引脚的功能，AF：复用功能*/
    TIM_TimeBaseInitTypeDef t;
    t.TIM_Prescaler = 8399; //预分频值   10000HZ=TIM13_CLK  将84M变为10000 这个8399是通过一个分频公式算出来

    t.TIM_CounterMode = TIM_CounterMode_Down; //递减模式
    t.TIM_Period = f;                         //N值，由10000变为对应音符的频率
    t.TIM_RepetitionCounter = 0;              //不需要重复计数
    TIM_TimeBaseInit(TIM13, &t);
    //3

    //输出通道的配置
    TIM_OCInitTypeDef t_oc;
    t_oc.TIM_OCMode = TIM_OCMode_PWM2;         // 因为递减模式，所以选择PWM2
    t_oc.TIM_OCPolarity = TIM_OCPolarity_High; // 高电平为有效电平
    // 试题：注意这个TIM_OutputState，还有另外一个带N的属性（只针对高级定时器）
    t_oc.TIM_OutputState = TIM_OutputState_Enable;
    t_oc.TIM_Pulse = f * 0.9; // 比较寄存器里面的值，这个里面的0.9是在不同的歌里面不同  占空比（高电平所占比）为10%
    // 注意是通道一的初始化，因为TIM13在通道1
    TIM_OC1Init(TIM13, &t_oc);
    TIM_OC1PreloadConfig(TIM13, TIM_OCPreload_Enable); //、

    //4
    //使能定时器
    TIM_ARRPreloadConfig(TIM13, ENABLE); //
    TIM_Cmd(TIM13, ENABLE);
}
void music_fun()
{
    for (x = 0; x < length; x++)
    {
        if (flag == 1)

        {
            flag = 0;
        }
        if (tune[x] == ZERO)
        {

            RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOF, DISABLE);
            RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM13, DISABLE);
            flag = 1;
        }

        music_init(tune[x]);
        if (flag == 1)
        {
            Delay_ms((uint32_t)(1000 * duration[x]));
            flag = 0;
        }
        else
            Delay_ms((uint32_t)(400 * duration[x]));
    }

    //关闭时钟
    RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM13, DISABLE);
    RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOF, DISABLE);
}